package com.ccp.dev.system.controller;

import com.ccp.dev.core.basic.annotion.Action;
import com.ccp.dev.core.basic.base.BaseController;
import com.ccp.dev.core.basic.consts.UrlConstants;
import com.ccp.dev.core.basic.model.SysAuditModelType;
import com.ccp.dev.core.basic.web.query.QueryFilter;
import com.ccp.dev.core.util.*;
import com.ccp.dev.system.model.BaseModuleInfo;
import com.ccp.dev.system.model.ColumnInfo;
import com.ccp.dev.system.model.TableInfo;
import com.ccp.dev.system.service.CodeGeneratorService;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringEscapeUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * @Author: dfz
 * @Date: 2019/5/16 14:07
 * @Description:代码生成控制器
 */

@Controller
@Action(ownermodel = SysAuditModelType.SYSTEM_SETTING)
@RequestMapping(UrlConstants.PROJECT_MODULE_SYSTEM + "/codeGen")
public class CodeGeneratorController extends BaseController {

    @Resource
    private CodeGeneratorService codeGenService;

    /**
     * 功能描述: 跳转到基本信息新增页
     *
     * @return: java.lang.String
     * @auther: dfz
     * @date: 2019/5/10 8:49
     */
    @Action(description="代码生成基本信息新增页页面跳转",exectype = "页面跳转日志")
    @RequestMapping(UrlConstants.VIEW_DISPATCH_PREFIX + UrlConstants.MODULE_FUNCTION_ADD_UPDATE)
    public String add(HttpServletRequest request,ModelMap modelMap) {
        String tableName = RequestUtil.getString(request,"tableName");
        Boolean batch = RequestUtil.getBoolean(request,"batch");
        String classForClassName = StringUtil.convertToCamelCase(RequestUtil.getString(request,"tableName"));
        modelMap.put("tableName",tableName);
        modelMap.put("isBatch",batch);
        modelMap.put("classForClassName",classForClassName);
        return "codeGen/add";
    }

    /**
     * 功能描述: 跳转到列表页
     *
     * @return: java.lang.String
     * @auther: dfz
     * @date: 2019/5/10 8:49
     */
    @Action(description="代码生成列表页页面跳转",exectype = "页面跳转日志")
    @RequestMapping(UrlConstants.VIEW_DISPATCH_PREFIX + UrlConstants.MODULE_FUNCTION_LIST)
    public String list() {
        return "codeGen/list";
    }

    /**
     * 功能描述: 跳转到列表页
     *
     * @return: java.lang.String
     * @auther: dfz
     * @date: 2019/5/10 8:49
     */
    @Action(description="代码生成表基本信息展示页面页面跳转",exectype = "页面跳转日志")
    @RequestMapping(UrlConstants.VIEW_DISPATCH_PREFIX + UrlConstants.MODULE_FUNCTION_SHOWINFO)
    public String showinfoForView(HttpServletRequest request,ModelMap modelMap) {
        String tableName = RequestUtil.getString(request,"tableName");
        String classForClassName = StringUtil.convertToCamelCase(RequestUtil.getString(request,"tableName"));
        modelMap.put("tableName",tableName);
        modelMap.put("classForClassName",classForClassName);
        return "codeGen/showinfo";
    }

    /**
     * 功能描述: 附带检索条件的分页查询
     *
     * @param: [request] http请求
     * @return: java.lang.Object
     * @auther: dfz
     * @date: 2019/5/10 8:51
     */
    @Action(description="代码生成附带检索条件的分页查询",exectype = "查询日志")
    @RequestMapping(UrlConstants.MODULE_FUNCTION_LIST)
    @ResponseBody
    public Object list(HttpServletRequest request) {

        QueryFilter queryFilter = new QueryFilter(request, true);
        //分页数据
        List<TableInfo> pageDatas = codeGenService.queryList(queryFilter);
        return success(pageDatas, queryFilter.getPageBean().getTotalCount());
    }

    /**
     * 功能描述: 附带检索条件的分页查询
     *
     * @param: [request] http请求
     * @return: java.lang.Object
     * @auther: dfz
     * @date: 2019/5/10 8:51
     */

    @Action(description="代码生成查询表字段信息",exectype = "查询日志")
    @RequestMapping(UrlConstants.MODULE_FUNCTION_SHOWINFO)
    @ResponseBody
    public Object showinfo(HttpServletRequest request) {
        String tableName  = RequestUtil.getSecureString(request, "tableName");
        return success(codeGenService.getTableColumnsByName(tableName));
    }

    @Action(description="代码生成查询约束列",exectype = "查询日志")
    @RequestMapping(UrlConstants.MODULE_FUNCTION_QUERYCOLUMNKEY)
    @ResponseBody
    public Object getTableColumnKeyByTableName(HttpServletRequest request){
        String tableName = RequestUtil.getSecureString(request,"tableName");
        return success(codeGenService.getTableColumnKeyByTableName(tableName));
    }

    /**
     *
     * 功能描述: 根据选中的表名称生成代码
     *
     * @param: [tableName] 要生成的表名，多个以‘,’连接
     * @return: java.lang.Object
     * @auther: dfz
     * @date: 2019/5/17 8:36
     */
    @RequestMapping(UrlConstants.MODULE_FUNCTION_GENCODES)
    @Action(description="代码生成根据选中的表名称生成代码",exectype = "编辑日志")
    public void generatorCode(HttpServletRequest request  , HttpServletResponse response){
        try{
            //解决“你的主机中的软件中止了一个已建立的连接”错误
//           response.addHeader("Access-Control-Allow-Origin", "*");
            //列信息
            Object   colsListObject=RequestUtil.getString(request,"colsList");
            List<ColumnInfo> columnInfos=null;
            ColumnInfo primaryColumn = null;
            TableInfo table = new TableInfo();
            String columnName = RequestUtil.getString(request,"primaryKeyColumn");
            String selectFlow = RequestUtil.getString(request,"flow");
            String columnTypeValue = columnName;
            String selectColumn = RequestUtil.getString(request,"selectColumn");
            if(colsListObject!=null && colsListObject != ""){
                //如果从前端页面传回来的列信息不为空，则转换成列信息的map集合
                List<Map> mapList =JSONObjectUtil.toBean(StringEscapeUtils.unescapeHtml(colsListObject.toString()), List.class);
                columnInfos= new ArrayList<>();
                for(Map map:mapList){
                    ColumnInfo columnInfo = (ColumnInfo)BeanUtils.mapToObject(map, ColumnInfo.class);
                    if(columnTypeValue.equals(columnInfo.getColumnName())){
                        String attrName = columnInfo.getAttrNameForProperty();
                        if(attrName.length()>1){
                            char charName  =attrName.charAt(1);
                            if(Character.isUpperCase(charName)){
                                attrName = StringUtil.convertToCamelFirstLowerCase(columnInfo.getAttrNameForProperty());
                            }else{
                                attrName = StringUtil.makeFirstLetterUpperCase(columnInfo.getAttrNameForProperty());
                            }
                        }

                        columnInfo.setAttrNameForMethod(attrName);
                        columnInfo.setAttrNameForProperty(StringUtils.uncapitalize(attrName));
                        primaryColumn = columnInfo;
                    }
                    columnInfos.add((ColumnInfo)BeanUtils.mapToObject(map, ColumnInfo.class));
                }
            }else{
                String tableName = RequestUtil.getString(request,"tableName");
                table.setTableName(tableName);
                ColumnInfo tempColumn = new ColumnInfo();
                tempColumn.setColumnName(columnTypeValue);
                table.setPrimaryKey(tempColumn);
                ColumnInfo columnInfo = codeGenService.getTablePrimaryKey(table);
                if(BeanUtils.isNotEmpty(columnInfo)){
                    String attrName = columnInfo.getAttrNameForProperty();
                    if(attrName.length()>1){
                        char charName  =attrName.charAt(1);
                        if(Character.isUpperCase(charName)){
                            attrName = StringUtil.convertToCamelFirstLowerCase(columnInfo.getAttrNameForProperty());
                        }else{
                            attrName = StringUtil.makeFirstLetterUpperCase(columnInfo.getAttrNameForProperty());
                        }
                    }

                    columnInfo.setAttrNameForMethod(attrName);
                    columnInfo.setAttrNameForProperty(StringUtils.uncapitalize(attrName));
                }
                primaryColumn = columnInfo;
            }
            BaseModuleInfo baseModuleInfo = new BaseModuleInfo(request);
            baseModuleInfo.setPrimaryKey(primaryColumn);
            Boolean isShowFull = RequestUtil.getBoolean(request,"isShowFull");
            baseModuleInfo.setShowFull(isShowFull);
            Boolean selectOpenMode = RequestUtil.getBoolean(request,"selectOpenMode");
            baseModuleInfo.setSelectOpenMode(selectOpenMode);
            baseModuleInfo.setSelectColumn(selectColumn);
            //清空输出流
            response.reset();
            //没有输入文件名称，自动生成文件名称
            String fileName  = baseModuleInfo.getFileName();
            if(StringUtil.isEmpty(fileName)){
                fileName  = baseModuleInfo.getModuleName() + DateFormatUtil.format(new Date(),"yyyyMMddHHmmss") + ".zip";
            }else {
                fileName = fileName+".zip";
            }
            //对文件名称进行编码防止出现乱码
            fileName= URLEncoder.encode(fileName, "UTF-8");
            //设置响应编码集
            response.setCharacterEncoding("UTF-8");
            //设置响应头
            response.setHeader("Content-disposition", "attachment; filename=" + fileName);
            response.setContentType("application/x-download; charset=UTF-8");
            String tableName = baseModuleInfo.getTableName();
            byte[] data;
            if(tableName.contains(",")){
                //包含多个表名时，调用批量生成代码
                data = codeGenService.batchGeneratorCode(baseModuleInfo,selectFlow);
            }else {
                //根据单个表生成代码
                data =codeGenService.generatorCode(baseModuleInfo,columnInfos,selectFlow);
            }
//            IOUtils.write(data, response.getOutputStream());
            FileUtil.downLoadFileByByte(request,response,data,fileName);
        }catch (Exception e){
            //TODO 异常没有处理，前端页面会没反应
            e.printStackTrace();
        }
    }

}
